<?php

namespace App\Services;

use App\Models\Category\Category;
use App\Models\Category\CategoryGroup;
use ElfSundae\Laravel\Hashid\Facades\Hashid;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;


class CategoryService
{
    public $category_group_id;

    /**
     * CategoryService constructor.
     * @param Request $request
     * @param $type
     */
    public function __construct(Request $request, $type)
    {
        $this->request = $request;
        //拿到类组的id
        $this->category_group_id = getCategoryGroupIdByName($type);
    }

    /**
     * 获取分类列表
     *
     */
    public function list()
    {
        //先处理传过来的搜索数据
        $this->formatIndexQuery($this->request);
        /**
         * 如果你只需要从数据表中获取一行数据，你可以使用 first 方法。该方法返回一个 stdClass 对象
         * 如果你甚至不需要整行数据，则可以使用 value 方法从记录中获取单个值。该方法将直接返回该字段的值
         * 如果是通过 id 字段值获取一行数据，可以使用 find 方法
         * 如果你想获取单列数据的集合，则可以使用 pluck 方法。
         * 如果你需要处理上千上万条数据库记录，你可以考虑使用 chunk 方法。该方法每次获取结果集的一小块，并将其传递给 Closure 函数进行处理。该方法在 Artisan 命令 中处理大量查询数据的时候非常有用
         * 查询构造器还提供了各种聚合方法，比如 count，max，min，avg，还有 sum。
         */
        //获取该类组允许的最大层级数

        $level = CategoryGroup::query()->where('id', $this->category_group_id)->value('depth');
        //按条件查询分类数据，并做好排序
        $data = Category::query()
            ->pimp()
            ->where('category_group_id', $this->category_group_id)
            ->where('level', '<=', $level)
            ->select('id', 'id as value', 'nickname as title', 'nickname as label', 'pid', 'top_id', 'nickname', 'name', 'path', 'weigh', 'type', 'status', 'image', 'keywords', 'description')
            ->orderBy('weigh', 'desc')
            ->orderBy('created_at', 'desc')
            ->orderBy('id', 'desc')
            ->get();
        //添加唯一的hash_id
        foreach ($data as $key => $item) {
            $item->hash_id = Hashid::encode($item->id);
            $item->image_url = 'https://shop--api.oss-cn-beijing.aliyuncs.com/shu1.png';
            $data[$key] = $item;

        }
        // 生成树
        $tree = generateTree(objectToArray($data), 'value');

        return $tree;
    }

    /**
     * 创建分类
     *
     * @param Request $request
     * @return Category|bool
     */
    public function createCategory()
    {

        $this->request->offsetSet('category_group_id', $this->category_group_id);

        $category = new Category();

        //array_filter过滤掉数组中的空元素
        $category->fill(array_filter($this->request->all()));

        $category->save();

        return $category;
    }

    /**
     * 更新分类
     *
     * @param $id
     * @param Request $request
     */
    public function updateCategory($id)
    {
        $category = Category::query()->findOrFail($id);

        $category->fill($this->request->all());

        $category->save();

        return $category;
    }

    /**
     * 验证分类标识
     *
     * @param $pid
     * @param $value
     * @param int $exclude
     * @return bool
     */
    public function checkCategoryName($pid, $value, $exclude = 0)
    {
        return $this->checkCategoryField('name', $value, $pid, $exclude);
    }


    /**
     * 验证分类昵称
     *
     * @param $pid
     * @param $value
     * @param int $exclude
     * @return bool
     */
    public function checkCategoryNickname($pid, $value, $exclude = 0)
    {
        return $this->checkCategoryField('nickname', $value, $pid, $exclude);
    }

    /**
     * 验证分类级别
     *
     * @param $pid
     * @param $value
     * @param int $exclude
     * @return bool
     */
    public function checkCategoryLevel($pid, $value, $exclude = 0)
    {
        return $this->checkCategoryField('level', $value, $pid, $exclude);
    }

    /**
     * 缓存分类数据
     *
     * @param $id
     * @param $data
     * @return bool
     */
    public function cacheCategory($id, $data)
    {
        return Cache::put('category:' . $id, $data, 60 * 60 * 24 + rand(0, 9999));
    }

    /**
     * 删除缓存分类数据
     *
     * @param $id
     * @return bool
     */
    public function delCacheCategory($id)
    {
        return Cache::forget('category:' . $id);
    }


    /**
     * 获取分类缓存数据
     *
     * @param $id
     */
    public function getCacheCategory($id)
    {
        $category = Cache::get('category:' . $id);

        if (empty($category)) {
            $category = Category::query()->find($id);
            $this->cacheCategory($id, $category);
        }

        return $category;
    }

    /**
     * 验证字段值是否重复
     *
     * @param $field
     * @param $value
     * @param $pid
     * @param int $exclude
     * @return bool
     */
    private function checkCategoryField($field, $value, $pid, $exclude = 0)
    {
        // 不存在父ID
        if (empty($pid)) {
            $data = Category::query()
                ->where('category_group_id', $this->category_group_id)
                ->where($field, $value)
                ->when($exclude > 0, function ($q) use ($exclude) {
                    $q->where('id', '<>', $exclude);
                })
                ->select('id')
                ->first();
            if (empty($data)) {
                return true;
            }

            return false;
        }

        $parent = $this->getCacheCategory($pid);

        if (empty($parent)) {
            return false;
        }

        if (empty($parent->top_id)) {
            $top_id = $parent->id;
        } else {
            $top_id = $parent->top_id;
        }

        $data = Category::query()
            ->where('category_group_id', $this->category_group_id)
            ->where(compact('top_id'))
            ->where(compact('pid'))
            ->where('level', $parent->level + 1)
            ->where($field, $value)
            ->when($exclude > 0, function ($q) use ($exclude) {
                $q->where('id', '<>', $exclude);
            })
            ->select('id')
            ->first();

        if (empty($data)) {
            return true;
        }

        return false;
    }

    /**
     * 处理搜索数据
     *
     * @param Request $request
     * @return Request
     */
    public function formatIndexQuery(Request $request)
    {
        $category_model = new Category();

        $searchableModels = $category_model->searchableModels ?? [];

        if (empty($searchableModels)) return $request;

        foreach ($request->all() as $key => $value) {
            //data_get 函数使用「.」符号从多维数组或对象中根据指定键检索值,default支持默认值，没有返回默认值
            $field_model = data_get($searchableModels, $key, '');

            if (!empty($field_model)) {
                //str_replace() 函数替换字符串中的一些字符（区分大小写）。
                $val = str_replace('field', $value, $field_model);
                //添加到$request数组中
                $request->offsetSet($key, $val);
            }
        }

        return $request;
    }
}
